package effectiveJava.DelayQueue;

import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * Created by dongyuncong on 2017/9/4.
 * todo  DelayQueue主要用于放置实现了Delay接口的对象，其中的对象只能在其时刻到期时才能从队列中取走。这种队列是有序的，
 * todo  即队头的延迟到期时间最短。如果没有任何延迟到期，那么久不会有任何头元素，并且poll()将返回null（正因为这样，你不能将null放置到这种队列中）；
 * todo  每次出队的时候只会判断对手的元素是否到期，到期才能取出队首，所以要根据延时结束时间排序
 */
public class DelayedEntity implements Delayed {

    private final long delayTime; //延迟时间
    private final long expireTime;  //到期时间
    private int index;   //数据

    public DelayedEntity(long delay, int index) {
        delayTime = delay;
        this.index = index;
        expireTime = System.currentTimeMillis() + delay;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(expireTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    /*todo 队列中的Delayed必须实现compareTo来指定元素的顺序。比如让延时时间最长的放在队列的末尾,应该让最先到期的元素，排在队首，因为出队的时候只会判断对手的元素是否到期，到期才能取出队首，所以此处根据延时结束时间排的序！*/
    @Override
    public int compareTo(Delayed o) {
        DelayedEntity entity = (DelayedEntity) o;
        return expireTime == ((DelayedEntity) o).expireTime ? 0 : expireTime > entity.expireTime ? 1 : -1;
    }

    @Override
    public String toString() {
        return "DelayedEntity{" +
                "delayTime=" + delayTime +
                ", expireTime=" + new Date(expireTime) +
                ", index=" + index +
                '}';
    }
}
